<template>
  <div class="ctf-question" style="margin-top: 12px;">
    <div
      class="question-result"
      v-if="
        showAnswerResult &&
          question.flagType === 3 &&
          (!isGrader ||
            (question.flagType != 3 &&
              (!question.userAnswer ||
                !(question.userAnswerList && question.userAnswerList.length))))
      "
    >
      <!-- <div class="question-result" v-if="showAnswerResult && !isGrader && question.flagType === 3"> -->
      <img :src="correctImg" alt="" v-if="answerRight()" />
      <span v-else-if="question.answerResult == 2" style="color: rgb(255, 153, 0);">等待评分</span>
      <img :src="errorImg" alt="" v-else />
    </div>
    <div class="question-result" v-if="isGrader">
      <Button
        type="primary"
        :disabled="!hasUserAnswer(question.userAnswer)"
        @click="
          $refs.grade.show()
          maxNum = question.score
          title = question.name
        "
        v-if="isGrader && question.flagType === 3"
        >评分</Button
      >
    </div>
    <div class="title-wrapper" :class="{ isGrader: isGrader && question.flagType === 3 }">
      <Checkbox
        v-if="showChecked"
        label=""
        @on-change="handleSelect($event, question)"
        v-model="question._checked"
        :disabled="getDisabled(question)"
      ></Checkbox>
      <span style="margin-right:0px">{{ index + 1 }}、</span>
      <span>{{ question.name }}</span>
      <span v-if="showScore">({{ question.score }}分)</span>
      <Tag color="blue">{{ question.matchMode != 3 ? 'CTF' : '问答题' }}</Tag>
      <Tag
        color="green"
        v-if="question.type || question.category"
        v-text="question.type || question.category"
      ></Tag>
      <Tag v-if="question.visibility" class="question-visibility" color="purple">{{
        question.visibility | filterIsPublic
      }}</Tag>
      <Tag color="cyan" v-if="question.matchMode != 3">{{
        [1, '1', 'true'].includes(question.needEnv) ? '需要环境' : '不需要环境'
      }}</Tag>
      <span v-if="question.flagType == 3 && showGrade" style="margin-left: 8px;">{{
        question.showRight === 2 ? '未评分' : `得分:${question.examScore}`
      }}</span>
      <span
        v-if="question.flagType != 3 && (question.examScore || question.examScore == 0)"
        style="margin-left: 8px;"
        >得分:{{ question.examScore }}</span
      >
      <span class="question-action" style="float:right;">
        <slot name="action" v-bind:question="question" v-bind:index="index"> </slot>
      </span>
    </div>
    <div class="answer-wrapper">
      <p v-text="question.description"></p>
      <p v-if="pattern === 'answer'">
        <!-- 非提交报告的ctf题型，使用长文本输入框输入答案 -->
        <template v-if="question.flagType != 3">
          <template v-if="question.userAnswerList.length > 0">
            <template v-for="item in conut">
              <div :key="item.id" style="display: flex; justify-content: space-between;">
                <Input
                  :key="item"
                  v-model.trim="questionAnswer[item - 1]"
                  :autosize="{ minRows: 2, maxRows: 6 }"
                  :maxlength="200"
                  type="textarea"
                  style="width: 70%; margin-bottom: 10px"
                  class="input_width_box"
                  :disabled="disabledAnswer"
                  @on-blur="inputFlagAnswer($event, question, index)"
                />
                <div v-if="showAnswerResult" style="margin-right: 10px">
                  <img
                    :src="correctImg"
                    alt=""
                    v-if="
                      question.flagTxt &&
                        question.flagTxt.split(', ').includes(questionAnswer[item - 1])
                    "
                  />
                  <img :src="errorImg" alt="" v-else />
                  <!-- <img
                  :src="correctImg"
                  alt=""
                  v-if="answerRightMultiFlag(item, index)"
                  /> -->
                  <!-- <img :src="errorImg" alt="" v-else /> -->
                </div>
              </div>
            </template>
          </template>
          <template v-else>
            <p class="flex-between mr10" style="color: var(--status-no)">
              此题未做答 <img :src="errorImg" alt="" />
            </p>
          </template>
        </template>
        <!-- 提交报告的ctf题型，使用富文本输入框输入答案 -->
        <template v-else>
          <quill-editor
            ref="myQuillEditor"
            v-model="questionAnswer[0]"
            v-if="!disabledAnswer || question.userAnswer"
            @focus="onEditorFocus($event)"
            @blur="onEditorBlur($event, question, index)"
            :options="disabledAnswer ? disabledOption : editorOption"
            class="editorShow"
            style="width:100%;display:block;height:100px;margin-bottom:50px;"
          ></quill-editor>
          <span style="color:#f90" v-if="!disabledAnswer">
            <Icon
              type="ios-information-circle-outline"
            />仅允许粘贴文本内容，粘贴内容中的图片、链接和样式将无效</span
          >
          <Upload
            ref="upload"
            style="display:inline-block"
            :show-upload-list="false"
            :on-success="handleSuccess"
            v-if="!disabledAnswer"
            :on-format-error="handleFormatErrorImg"
            :format="['jpg', 'jpeg', 'png', 'gif']"
            multiple
            :action="uploadUrl"
          >
            <Button icon="ios-cloud-upload-outline" id="imgUploadBtn" v-show="false"></Button>
          </Upload>
          <Upload
            ref="fileUpload"
            style="display:inline-block"
            :show-upload-list="false"
            :on-success="handleFileSuccess"
            v-if="!disabledAnswer"
            :on-format-error="handleFormatErrorFile"
            :format="['pdf']"
            multiple
            :action="fileUploadUrl"
          >
            <Button icon="ios-cloud-upload-outline" id="fileUploadBtn" v-show="false"></Button>
          </Upload>
          <template v-if="showAnswerResult && question.userAnswer == ''">
            <p class="flex-between mr10" style="color:var(--status-no)">
              此题未做答
            </p>
          </template>
        </template>
      </p>
      <p v-if="question.filePath || question.attachmentPath">
        附件：<a
          :href="'/api/minio/download?path=' + (question.filePath || question.attachmentPath)"
          style="margin:0 5px;"
          download=""
          >{{ question.fileName || question.attachmentName }}</a
        >
      </p>
      <p v-if="showWriteUp && question.writeUpPath">
        解题思路：<a
          :href="'/api/minio/download?path=' + question.writeUpPath"
          style="margin:0 5px;"
          download=""
          >{{ question.writeUpName }}</a
        >
      </p>
      <!-- <div v-if="showAnswerResult && (!question.userAnswer || !(question.userAnswerList && question.userAnswerList.length))" style="color: #FF6854;">
				此题未作答
			</div> -->
      <p v-if="showRightAnswer && question.flagTxt">
        参考答案：<span class="right-answer">{{ question.flagTxt }}</span>
      </p>
      <p
        v-if="showRightAnswer && question.flagTxt == '' && question.flagType == 0"
        v-for="(item, index) of question.cftAnswers"
        :key="index"
      >
        第{{ index + 1 }}个正确答案：<span class="right-answer">{{ item.flag }}</span>
      </p>
    </div>
    <grade :minNum="0" :maxNum="maxNum" ref="grade" @on-change="marking" :title="title"></grade>
  </div>
</template>
<script>
import common from './mixin'
import { marking } from '@/api/exam'
import { quillEditor } from 'vue-quill-editor' // 调用编辑器
import Grade from '@/components/grade/grade'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
//引入Qill插件
import Quill from 'quill'
let Link = Quill.import('formats/link')
// 自定义a链接
class FileBlot extends Link {
  // 继承Link Blot
  static create(value) {
    let node = undefined
    if (value && !value.href) {
      // 适应原本的Link Blot
      node = super.create(value)
    } else {
      // 自定义Link Blot
      node = super.create(value.href)
      node.innerText = value.innerText
      node.href = value.href
      node.id = value.id
      node.setAttribute('title', '点击可下载:' + value.innerText)
      node.setAttribute('data-value', value.dataValue)
    }
    return node
  }
}
FileBlot.blotName = 'link'
FileBlot.tagName = 'A'
//注册FileBlot
Quill.register(FileBlot)
const toolbarOptions = [
  ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
  [{ header: 1 }, { header: 2 }], // 1、2 级标题
  [{ script: 'sub' }, { script: 'super' }], // 上标/下标
  [{ indent: '-1' }, { indent: '+1' }], // 缩进
  [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
  [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  [{ align: [] }], // 对齐方式
  ['clean'], // 清除文本格式
  ['image'] // 链接、图片、视频
]

export default {
  name: 'CtfQuestion',
  mixins: [common],
  components: { quillEditor, Grade },
  watch: {
    question: {
      immediate: true,
      deep: true,
      handler: function(newVal) {
        if (newVal && !newVal.flagTxt) {
          newVal.flagTxt = ''
          if (newVal.cftAnswers) {
            newVal.flagTxt = (newVal.cftAnswers.map((item) => item.flag) || []).join(', ')
          }
          if (
            this.question.userAnswerList &&
            this.question.userAnswerList.length &&
            this.question.flagType == 3
          ) {
            this.questionAnswer[0]
              ? this.questionAnswer[0].replaceAll('["', ' ').replaceAll('"]', ' ')
              : this.questionAnswer[0]
          }
        }
      }
    }
  },
  props: {
    question: {
      type: Object,
      validator(value) {
        //6-ctf
        return value.modeCode.toString() === '6' && value.name
      }
    },
    showGrade: {
      type: Boolean,
      default: false
    },
    showWriteUp: {
      type: Boolean,
      default: false
    },
    paperid: {
      type: String,
      default: ''
    },
    userId: {
      type: String,
      default: ''
    },
    examid: {
      type: String,
      default: ''
    },
    isGrader: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      questionAnswer: [],
      conut: 0,
      title: '',
      maxNum: 10,
      uploadUrl: '/api/minio/upload/permanent?visibility=company&type=images&bucket=images',
      fileUploadUrl: '/api/minio/upload/permanent?visibility=company&type=docs&bucket=docs',
      disabledOption: {
        modules: {
          toolbar: false
        },
        placeholder: ''
      },
      editorOption: {
        modules: {
          clipboard: {
            // 粘贴版，处理粘贴时候带图片
            matchers: [[Node.ELEMENT_NODE, this.handleCustomMatcher]]
          },
          toolbar: {
            container: toolbarOptions, //工具菜单栏配置
            handlers: {
              image: (value) => {
                if (value) {
                  document.querySelector('#imgUploadBtn').click()
                } else {
                  this.quill.format('image', false)
                }
              },
              file: (value) => {
                if (value) {
                  document.querySelector('#fileUploadBtn').click()
                }
              }
            }
          }
        },
        placeholder: '请编辑内容' //提示
      }
    }
  },
  methods: {
    answerRightMultiFlag(answer, index) {
      let rightAnswers = this.question.cftAnswers.map((item) => item.flag)
      let prevUserAnswer = this.question.userAnswerList.slice(0, index)
      return rightAnswers.includes(answer) && !prevUserAnswer.includes(answer)
    },
    hasUserAnswer(userAnswer) {
      if (userAnswer && userAnswer.trim() !== '') {
        return true
      } else {
        return false
      }
    },
    // 上传文件，上传成功后将文件地址生成超链接插入富文本光标处
    handleFileSuccess(res) {
      if (res.code == 1) {
        // 获取光标所在位置
        let quill = this.$refs.myQuillEditor.quill
        let length = quill.getSelection().index || 1
        // 插入图片，res为服务器返回的图片链接地址
        let url = `${this.baseURL}/minio/download?path=${res.data}` // `/Learn/${res.data}`
        quill.insertEmbed(length, 'text', '[')
        quill.insertEmbed(
          length + 1,
          'link',
          {
            href: url,
            innerText: res.info.originalName,
            id: res.info.id,
            dataValue: `/Learn/${res.data}`
          },
          'api'
        )
        quill.insertEmbed(length + res.info.originalName.length + 1, 'text', ']')
      } else {
        this.$Message.error(data.message)
      }
    },
    // 图片格式验证失败时的回调函数
    handleFormatErrorImg() {
      this.$Message.warning('仅允许上传jpg,jpeg,png,gif格式文件')
    },
    // 格式验证失败时的回调函数
    handleFormatErrorFile() {
      this.$Message.warning('仅允许上传pdf格式文件')
    },
    // 上传图片，上传成功后使用图片地址生成img元素插入富文本光标处
    handleSuccess(res) {
      if (res.code == 1) {
        // 获取光标所在位置
        let quill = this.$refs.myQuillEditor.quill
        let length = quill.getSelection().index
        // 插入图片，res为服务器返回的图片链接地址
        let url = `/Learn/${res.data}`
        quill.insertEmbed(length, 'image', url)
      } else {
        this.$Message.error(data.message)
      }
    },
    selectAnswer(userAnswer, question, index) {
      if (this.pattern === 'answer') {
        this.$emit('handleAnswerSelect', question, index, userAnswer)
      }
    },
    onEditorBlur(userAnswer, question, index) {
      if (this.pattern === 'answer') {
        this.$emit('handleAnswerSelect', question, index, userAnswer)
      }
    },
    // 显示区禁止编辑
    onEditorFocus(event) {
      if (this.disabledAnswer) {
        // 视状态禁用输入
        event.enable(false)
      }
    },
    // 粘贴时候，除纯文本外的内容全部忽略
    handleCustomMatcher(node, Delta) {
      let ops = []
      Delta.ops.forEach((op) => {
        if (op.insert && typeof op.insert === 'string') {
          // 只有纯文本是字符串类型，其他包括图片、文件等，均忽略掉
          ops.push({
            // 只保留粘贴内容，格式全部舍弃
            insert: op.insert
          })
        }
        if (op.insert && op.insert.image && op.insert.image.indexOf('/Learn') !== -1) {
          ops.push({
            // 保留本系统包含的图片
            insert: op.insert
          })
        }
      })
      Delta.ops = ops
      return Delta
    },
    marking(score) {
      marking([
        {
          id: this.question.userAnswerId,
          score,
          showRight: score > 0 ? 1 : 0,
          examinationId: this.examid,
          paperId: this.paperid,
          userId: this.userId
        }
      ]).then(({ code, message }) => {
        if (code !== 1) {
          this.$Message.warning(message)
          return
        }
        this.$Message.success('评分成功')
        document.body.click() // 控制评分组件消失
        this.$emit('on-marking')
      })
    }
  },
  mounted() {
    if (this.disabledAnswer && this.$refs.myQuillEditor) {
      this.$refs.myQuillEditor.quill.enable(false)
    }
    if (this.question.userAnswerList && this.question.userAnswerList.length) {
      this.questionAnswer = this.question.userAnswerList
    } else if (this.question.userAnswer !== '') {
      this.questionAnswer.push(this.question.userAnswer)
    } else {
      this.questionAnswer = []
    }
    // this.conut = this.question.flagCount || this.question.userAnswerList.length
    if (this.question.flagCount) {
      this.conut = this.question.flagCount
    } else if (this.question.userAnswerList) {
      this.conut = this.question.userAnswerList.length
    } else {
      this.conut = 1
    }
    if (this.question.userAnswer) {
      this.question.userAnswer = this.question.userAnswer
        .replaceAll('["', ' ')
        .replaceAll('"]', ' ')
    }
    if (
      this.question.userAnswerList &&
      this.question.userAnswerList.length &&
      this.question.flagType == 3
    ) {
      this.questionAnswer[0] = this.questionAnswer[0].replaceAll('["', ' ').replaceAll('"]', ' ')
      console.log(this.questionAnswer[0], 123)
    }
  }
}
</script>
<style scoped src="./question.css"></style>
<style scoped>
.title-wrapper.isGrader {
  width: calc(100% - 86px);
}
.editorShow {
  width: calc(100% - 86px);
}
.poptip-title {
  width: 268px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.poptip-content {
  height: 36px;
}
</style>
